package org.cjlm.vo;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public abstract class SuperVO {
    private Map<String, List<SuperVO>> children;

    public abstract String getTableName();
    public abstract String getPrimarykeyName();
    public abstract String getParentName();

    public List<SuperVO> getChildren() {
        if(this.children != null && children.size() > 0){
            if(this.children.size() == 1){
                return this.children.values().iterator().next();
            }else{
                List<SuperVO> result = new ArrayList<>();
                for(Iterator<String> iter = this.children.keySet().iterator(); iter.hasNext();){
                    String key = iter.next();
                    List<SuperVO> value = this.children.get(key);
                    result.addAll(value);
                }
                return result;
            }
        }

        return null;
    }

    public List<SuperVO> getChildren(String clazzName) {
        if(this.children == null || this.children.size() == 0){
            return null;
        }else{
            return this.children.get(clazzName);
        }
    }

    public void setChildren(List<SuperVO> children) {
        if(children != null && children.size() > 0){
            this.children = new HashMap<>();
            this.children.put(children.get(0).getClass().getName(), children);
        }
    }

    public void addChildren(List<SuperVO> children) {
        if(this.children == null || this.children.size() == 0){
            setChildren(children);
        }else{
            if(children != null && children.size() > 0){
                String key = children.get(0).getClass().getName();
                if(this.children.containsKey(key)){
                    List<SuperVO> list = this.children.get(key);
                    list.addAll(children);
                }else{
                    this.children.put(key, children);
                }
            }
        }
    }

    // 统一的反射字段操作方法
    private Field findAccessibleField(String fieldName) {
        Class<?> clazz = this.getClass();
        while (clazz != null && clazz != Object.class)  {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                if (!Modifier.isStatic(field.getModifiers()))  {
                    field.setAccessible(true);
                    return field;
                }
            } catch (NoSuchFieldException ignored) {}
            clazz = clazz.getSuperclass();
        }
        return null;
    }

    // 类型转换统一方法
    private Object convertValueType(Object value, Class<?> targetType) {
        if (value == null || targetType.isInstance(value))  {
            return value;
        }

        try {
            String strValue = value.toString();
            if (targetType == String.class)  return strValue;
            if (targetType == int.class  || targetType == Integer.class)  return Integer.parseInt(strValue);
            if (targetType == long.class  || targetType == Long.class)  return Long.parseLong(strValue);
            if (targetType == double.class  || targetType == Double.class)  return Double.parseDouble(strValue);
            if (targetType == boolean.class  || targetType == Boolean.class)  return Boolean.parseBoolean(strValue);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Type conversion failed: " + value + " to " + targetType.getSimpleName());
        }
        return value;
    }

    // 统一的字段访问方法
    public Object getFieldValue(String fieldName) {
        Field field = findAccessibleField(fieldName);
        if (field == null) return null;

        try {
            return field.get(this);
        } catch (IllegalAccessException e) {
            handleReflectionException(e);
            return null;
        }
    }

    public boolean setFieldValue(String fieldName, Object value) {
        Field field = findAccessibleField(fieldName);
        if (field == null) return false;

        try {
            if (Modifier.isFinal(field.getModifiers()))  {
                throw new IllegalAccessException("Cannot set final field: " + fieldName);
            }

            Object convertedValue = convertValueType(value, field.getType());
            field.set(this,  convertedValue);
            return true;
        } catch (IllegalAccessException e) {
            handleReflectionException(e);
            return false;
        }
    }

    // 简化主键操作方法
    public String getPrimaryKeyValue() {
        return (String) getFieldValue(getPrimarykeyName());
    }

    public boolean setPrimaryKeyValue(Object value) {
        return setFieldValue(getPrimarykeyName(), value);
    }

    // 字段名列表获取
    public List<String> getAllFieldNames() {
        List<String> fieldNames = new ArrayList<>();
        Class<?> clazz = this.getClass();
        while (clazz != null && clazz != Object.class  && SuperVO.class.isAssignableFrom(clazz))  {
            for (Field field : clazz.getDeclaredFields())  {
                if (!Modifier.isStatic(field.getModifiers())  && !"children".equals(field.getName()))  {
                    fieldNames.add(field.getName());
                }
            }
            clazz = clazz.getSuperclass();
        }
        return fieldNames;
    }

    // 统一的异常处理方法
    private void handleReflectionException(Exception e) {
        System.err.println("Reflection  operation failed: " + e.getMessage());
        e.printStackTrace();
    }
}